/*
 *
 *  *    Copyright 2020-2021 Luter.me
 *  *
 *  *    Licensed under the Apache License, Version 2.0 (the "License");
 *  *    you may not use this file except in compliance with the License.
 *  *    You may obtain a copy of the License at
 *  *
 *  *      http://www.apache.org/licenses/LICENSE-2.0
 *  *
 *  *    Unless required by applicable law or agreed to in writing, software
 *  *    distributed under the License is distributed on an "AS IS" BASIS,
 *  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  *    See the License for the specific language governing permissions and
 *  *    limitations under the License.
 *
 */

package com.luter.heimdall.samples.jfinal.controller;

import com.jfinal.aop.Inject;
import com.jfinal.core.Controller;
import com.jfinal.core.Path;
import com.luter.heimdall.core.authorization.provider.DocumentUsersDataProvider;
import com.luter.heimdall.core.authorization.provider.model.UserDO;
import com.luter.heimdall.core.authorization.store.AuthorizationStore;
import com.luter.heimdall.core.config.ConfigManager;
import com.luter.heimdall.core.config.HeimdallProperties;
import com.luter.heimdall.core.details.UserDetails;
import com.luter.heimdall.core.exception.HeimdallException;
import com.luter.heimdall.core.exception.HeimdallExcessiveAttemptsException;
import com.luter.heimdall.core.limiter.MemoryCachedPasswordRetryLimiter;
import com.luter.heimdall.core.manager.HeimdallAuthorizationManager;
import com.luter.heimdall.core.token.SimpleToken;
import com.luter.heimdall.core.utils.ObjUtil;
import com.luter.heimdall.core.utils.crypto.Md5Util;

/**
 * The type User controller.
 *
 * @author luter
 */
@Path("/user")
public class UserController extends Controller {

    /**
     * The Retry limiter.
     */
    @Inject
    MemoryCachedPasswordRetryLimiter retryLimiter;

    /**
     * The Authorization manager.
     */
    @Inject
    HeimdallAuthorizationManager authorizationManager;

    /**
     * Index.
     */
    public void index() {
        renderText("首页");
    }

    /**
     * Login.
     */
    public void login() {
        final String username = getPara("username");
        final String password = getPara("password");
        final UserDO userVO = DocumentUsersDataProvider.loadUserByUserName(username);
        if (null == userVO) {
            throw new HeimdallException("incorrect user name or password.");
        }
        final HeimdallProperties config = ConfigManager.getConfig();
        //看看是不是已经锁定了，锁定了，就只能等。
        final int count = retryLimiter.availableTimes(username);
        if (count <= 0) {
            throw new HeimdallException("Your account is locked. Please try again after " + config.getLimiter().getLockedDuration() + " Minutes");
        }
        if (!Md5Util.matches(password, userVO.getPassword())) {
            //还可以重试，那单纯就是密码不对
            if (!retryLimiter.overLimitWhenIncremented(username)) {
                String text = (count - 1) == 0 ? "没戏了，别试了,锁你:"
                        + config.getLimiter().getLockedDuration() + "分钟" : "还可尝试:" + (count - 1) + "次";
                throw new HeimdallException("incorrect user name or password." +
                        " ensure both user account and password are valid.|=" + text);
            }
            throw new HeimdallExcessiveAttemptsException();
        }
        final String login = authorizationManager.getAuthenticationManager()
                .login(new UserDetails().setAppId(userVO.getAppId())
                        .setUserId(userVO.getUserId())
                        .setAttributes(ObjUtil.ConvertObjectToMap(userVO, "password", "perms")));
        renderText(login);
    }

    /**
     * Current.
     */
    public void current() {
        final SimpleToken currentToken = authorizationManager
                .getAuthenticationManager().getCurrentToken(true);
        renderJson(currentToken);
    }

    /**
     * Reset auth.
     */
    public void resetAuth() {
        final String appId = getPara("appId");
        final String userId = getPara("userId");
        final AuthorizationStore authorizationStore = authorizationManager.getAuthorizationStore();
        authorizationStore.removeUserAuthorities(new UserDetails().setAppId(appId).setUserId(userId));
        renderText("成功");
    }
}
